package org.tinaelle.hibernate.audit;

import java.io.Serializable;
import java.util.Vector;

import org.hibernate.CallbackException;
import org.hibernate.EmptyInterceptor;
import org.hibernate.type.Type;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.tinaelle.server.domain.AdObject;

/**
 * DOCUMENT ME!
 * 
 * @author $author$
 * @version $Revision$
 */
public class HibernateAuditInterceptor extends EmptyInterceptor implements ApplicationContextAware {
	private static final long	serialVersionUID	= -3073850856829239762L;

	private ActionLogger	  theLogger;

	public static boolean	  isActive	         = true;

	public void setTheLogger(final ActionLogger theLogger) {
		this.theLogger = theLogger;
	}

	/**
	 * Creates a new instance of HibernateLoggingInterceptor
	 */
	public HibernateAuditInterceptor() {
	} // end HibernateAuditInterceptor()

	/**
	 * DOCUMENT ME!
	 * 
	 * @param entity
	 *            DOCUMENT ME!
	 * @param id
	 *            DOCUMENT ME!
	 * @param state
	 *            DOCUMENT ME!
	 * @param propertyNames
	 *            DOCUMENT ME!
	 * @param types
	 *            DOCUMENT ME!
	 * 
	 * @return DOCUMENT ME!
	 * 
	 * @throws CallbackException
	 *             DOCUMENT ME!
	 */
	@Override
	public boolean onLoad(final Object entity, final Serializable id, final Object[] state,
	        final String[] propertyNames, final Type[] types) throws CallbackException {
		return false;
	} // end onLoad()

	/**
	 * DOCUMENT ME!
	 * 
	 * @param entity
	 *            DOCUMENT ME!
	 * @param id
	 *            DOCUMENT ME!
	 * @param newValues
	 *            DOCUMENT ME!
	 * @param oldValues
	 *            DOCUMENT ME!
	 * @param propertyNames
	 *            DOCUMENT ME!
	 * @param types
	 *            DOCUMENT ME!
	 * 
	 * @return DOCUMENT ME!
	 * 
	 * @throws CallbackException
	 *             DOCUMENT ME!
	 */
	@Override
	public boolean onFlushDirty(final Object entity, final Serializable id, final Object[] newValues,
	        final Object[] oldValues, final String[] propertyNames, final Type[] types) throws CallbackException {
		for ( int i = 0; i < oldValues.length; i++ ) {
			if ( ( ( oldValues[ i ] != null ) && ( newValues[ i ] != null ) && !oldValues[ i ].equals( newValues[ i ] ) )
			        || ( ( oldValues[ i ] == null ) && ( newValues[ i ] != null ) )
			        || ( ( oldValues[ i ] != null ) && ( newValues[ i ] == null ) ) ) {
				System.err.println( entity + " change " + propertyNames[ i ] + ", old = " + oldValues[ i ] + ", new = "
				        + newValues[ i ] );
			}
		}
		if ( isActive && ( entity instanceof AdObject ) ) {
			theLogger.logThis( "Update", entity, propertyNames, getUserId() );
		} // end if

		return false;
	} // end onFlushDirty()

	@Override
	public int[] findDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState,
	        String[] propertyNames, Type[] types) {
		int[] result;
		Vector<Integer> newResult = new Vector<Integer>();
		for ( int i = 0; i < propertyNames.length; i++ ) {
			if ( !( propertyNames[ i ].equalsIgnoreCase( "Created" ) || propertyNames[ i ].equalsIgnoreCase( "Updated" )
			        || propertyNames[ i ].equalsIgnoreCase( "CreatedBy" ) || propertyNames[ i ]
			        .equalsIgnoreCase( "UpdatedBy" ) ) ) {
				if ( ( previousState[ i ] == null ) && ( currentState[ i ] != null ) ) {
					System.err.println( "Add : " + propertyNames[ i ] );
					newResult.add( i );
				} else if ( ( previousState[ i ] != null ) && ( currentState[ i ] == null ) ) {
					System.err.println( "Add : " + propertyNames[ i ] );
					newResult.add( i );
				} else if ( ( previousState[ i ] != null ) && ( currentState[ i ] != null )
				        && !previousState[ i ].equals( currentState[ i ] ) ) {
					System.err.println( "Add : " + propertyNames[ i ] );
					newResult.add( i );
				}

			} else {
				// System.err.println( "Skip : " + propertyNames[ i ] );
			}
		}

		result = new int[ newResult.size() ];
		for ( int i = 0; i < newResult.size(); i++ ) {
			result[ i ] = newResult.get( i ).intValue();
		}
		return result;
	}

	private Long getUserId() {
		return -1L;
	} // end getUserId()

	/**
	 * DOCUMENT ME!
	 * 
	 * @param entity
	 *            DOCUMENT ME!
	 * @param id
	 *            DOCUMENT ME!
	 * @param state
	 *            DOCUMENT ME!
	 * @param propertyNames
	 *            DOCUMENT ME!
	 * @param types
	 *            DOCUMENT ME!
	 * 
	 * @return DOCUMENT ME!
	 * 
	 * @throws CallbackException
	 *             DOCUMENT ME!
	 */
	@Override
	public boolean onSave(final Object entity, final Serializable id, final Object[] state,
	        final String[] propertyNames, final Type[] types) throws CallbackException {
		if ( isActive && ( entity instanceof AdObject ) ) {
			theLogger.logThis( "Create", entity, propertyNames, -getUserId() );
		} // end if

		return false;
	} // end onSave()

	/**
	 * DOCUMENT ME!
	 * 
	 * @param entity
	 *            DOCUMENT ME!
	 * @param id
	 *            DOCUMENT ME!
	 * @param state
	 *            DOCUMENT ME!
	 * @param propertyNames
	 *            DOCUMENT ME!
	 * @param types
	 *            DOCUMENT ME!
	 * 
	 * @throws CallbackException
	 *             DOCUMENT ME!
	 */
	@Override
	public void onDelete(final Object entity, final Serializable id, final Object[] state,
	        final String[] propertyNames, final Type[] types) throws CallbackException {
		if ( isActive && ( entity instanceof AdObject ) ) {
			theLogger.logThis( "Delete", entity, propertyNames, getUserId() );
		} // end if
	} // end onDelete()

	/**
	 * DOCUMENT ME!
	 * 
	 * @param arg0
	 *            DOCUMENT ME!
	 * 
	 * @throws BeansException
	 *             DOCUMENT ME!
	 */
	public void setApplicationContext(final ApplicationContext arg0) throws BeansException {
	} // end setApplicationContext()
} // end HibernateAuditInterceptor
